package com.fxu.framework.core.sql;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

/**
 * 查询、更新条件函数接口
 *
 * @author fangxu
 * @version 1.0.0
 */
interface SCompare<Chain extends SCompare<?, ?>, SE extends SEntity<?>> extends Serializable {
    /**
     * 实体类的类
     * @return 实体类的类
     */
    Class<SE> getClazz();

    /**
     * 实体类的类
     * @return 查询集合
     */
    List<SValue> getQueryList();

    /**
     * 设置查询条件
     * @param queryList 查询条件集合
     * @return 本类对象
     */
    default Chain where(List<SValue> queryList) {
        Class<SE> clazz = getClazz();
        for (SValue v : queryList) {
            if (clazz != null && v != null && v.getSType() != null && v.getField() != null && v.getValue() != null) {
                getQueryList().add(v);
            }
        }
        return (Chain)this;
    }

    /**
     * 设置查询条件
     * @param type 查询条件类型
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain where(SType type, SField field, Object value) {
        Class<SE> clazz = getClazz();
        if (type != null && clazz != null && field != null && value != null) {
            getQueryList().add(new SValue(type, field, value));
        }
        return (Chain)this;
    }

    /**
     * 设置查询条件
     * @param type 查询条件类型
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain where(SType type, SFunc<SE, ?> field, Object value) {
        return where(type, new SField<>(getClazz(), field), value);
    }

    /**
     * 设置查询条件
     * @param type 查询条件类型
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain where(SType type, Field field, Object value) {
        return where(type, new SField<>(field), value);
    }

    /**
     * 设置查询条件
     * @param type 查询条件类型
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain where(SType type, String field, Object value) {
        return where(type, new SField<>(getClazz(), field), value);
    }

    /**
     * 比较两个字段
     * @param type 比较类型
     * @param field1 查询条件字段
     * @param field2 对应另外一个字段
     * @return 本类对象
     */
    default Chain apply(SType type, SFunc<SE, ?> field1, SFunc<SE, ?> field2) {
        Class<SE> clazz = getClazz();
        if (type != null && clazz != null && field1 != null && field2 != null) {
            getQueryList().add(new SValue(type, new SField<>(getClazz(), field1), new SField<>(getClazz(), field2)));
        }
        return (Chain)this;
    }

    /**
     * 等于 =
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain eq(SFunc<SE, ?> field, Object value) {
        return where(SType.EQ, field, value);
    }

    /**
     * 不等于 !=
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain ne(SFunc<SE, ?> field, Object value) {
        return where(SType.NE, field, value);
    }

    /**
     * 大于 &gt;
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain gt(SFunc<SE, ?> field, Object value) {
        return where(SType.GT, field, value);
    }

    /**
     * 小于 &lt;
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain lt(SFunc<SE, ?> field, Object value) {
        return where(SType.LT, field, value);
    }

    /**
     * 大于等于 &gt;=
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain ge(SFunc<SE, ?> field, Object value) {
        return where(SType.GE, field, value);
    }

    /**
     * 小于等于 &lt;=
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain le(SFunc<SE, ?> field, Object value) {
        return where(SType.LE, field, value);
    }

    /**
     * 在里面 in (X,XX)
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain in(SFunc<SE, ?> field, Object value) {
        return where(SType.IN, field, value);
    }

    /**
     * 不在里面 not in (X,XX)
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain notIn(SFunc<SE, ?> field, Object value) {
        return where(SType.NOT_IN, field, value);
    }

    /**
     * id 在 ids 里面, ids = 1,2,3 查找 id = 4, 先查找[4,] 再查[4,%] 再查[%,4] 接着查[%,4,%]
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain sIn(SFunc<SE, ?> field, Object value) {
        return where(SType.S_IN, field, value);
    }

    /**
     * 模糊比较相似 like %XX%
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain like(SFunc<SE, ?> field, Object value) {
        return where(SType.LIKE, field, value);
    }

    /**
     * 模糊比较不相似 not like %XX%
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain notLike(SFunc<SE, ?> field, Object value) {
        return where(SType.NOT_LIKE, field, value);
    }

    /**
     * 模糊比较左边相似，右边模糊 like XX%
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain likeRight(SFunc<SE, ?> field, Object value) {
        return where(SType.LIKE_RIGHT, field, value);
    }

    /**
     * 字段是null
     * @param field 查询条件字段
     * @return 本类对象
     */
    default Chain isNull(SFunc<SE, ?> field) {
        return where(SType.IS_NULL, field, "NULL");
    }

    /**
     * 字段不是 null : not null
     * @param field 查询条件字段
     * @return 本类对象
     */
    default Chain notNull(SFunc<SE, ?> field) {
        return where(SType.NOT_NULL, field, "NULL");
    }

    /**
     * 字段是(null 或者 空)
     * @param field 查询条件字段
     * @return 本类对象
     */
    default Chain isEmpty(SFunc<SE, ?> field) {
        return where(SType.IS_EMPTY, field, "NULL");
    }

    /**
     * 字段不是 null 而且 不是 空
     * @param field 查询条件字段
     * @return 本类对象
     */
    default Chain notEmpty(SFunc<SE, ?> field) {
        return where(SType.NOT_EMPTY, field, "NULL");
    }

    /**
     * 范围查找, 大于等于value[0], 小于等于value[1]
     * @param field 查询条件字段
     * @param value 查询条件值
     * @return 本类对象
     */
    default Chain range(SFunc<SE, ?> field, Object value) {
        return where(SType.RANGE, field, value);
    }

    /**
     * 范围查找, 大于等于value1, 小于等于value2
     * @param field 查询条件字段
     * @param value1 查询大于等于条件值
     * @param value2 查询小于等于条件值
     * @return 本类对象
     */
    default Chain range(SFunc<SE, ?> field, Object value1, Object value2) {
        return where(SType.RANGE, field, Arrays.asList(value1, value2));
    }

    /**
     * 范围查找, 大于value1, 小于value2
     * @param field 查询条件字段
     * @param value1 查询大于条件值
     * @param value2 查询小于条件值
     * @return 本类对象
     */
    default Chain rangeNe(SFunc<SE, ?> field, Object value1, Object value2) {
        return where(SType.RANGE_NE, field, Arrays.asList(value1, value2));
    }

    /**
     * 非范围查找, 小于value1, 大于value2
     * @param field 查询条件字段
     * @param value1 查询小于条件值
     * @param value2 查询大于条件值
     * @return 本类对象
     */
    default Chain notRange(SFunc<SE, ?> field, Object value1, Object value2) {
        return where(SType.NOT_RANGE, field, Arrays.asList(value1, value2));
    }
}